View Javadoc
1   package org.apache.maven.surefire.common.junit3;
2   
3   /*
4    * Licensed to the Apache Software Foundation (ASF) under one
5    * or more contributor license agreements.  See the NOTICE file
6    * distributed with this work for additional information
7    * regarding copyright ownership.  The ASF licenses this file
8    * to you under the Apache License, Version 2.0 (the
9    * "License"); you may not use this file except in compliance
10   * with the License.  You may obtain a copy of the License at
11   *
12   *     http://www.apache.org/licenses/LICENSE-2.0
13   *
14   * Unless required by applicable law or agreed to in writing,
15   * software distributed under the License is distributed on an
16   * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
17   * KIND, either express or implied.  See the License for the
18   * specific language governing permissions and limitations
19   * under the License.
20   */
21  
22  import java.lang.reflect.Constructor;
23  import java.lang.reflect.InvocationTargetException;
24  import java.lang.reflect.Method;
25  import java.lang.reflect.Modifier;
26  import org.apache.maven.surefire.util.ReflectionUtils;
27  
28  /**
29   * Reflection facade for JUnit3 classes
30   *
31   */
32  public final class JUnit3Reflector
33  {
34      private static final String TEST_CASE = "junit.framework.Test";
35  
36      private static final String TEST_RESULT = "junit.framework.TestResult";
37  
38      private static final String TEST_LISTENER = "junit.framework.TestListener";
39  
40      private static final String TEST = "junit.framework.Test";
41  
42      private static final String ADD_LISTENER_METHOD = "addListener";
43  
44      private static final String RUN_METHOD = "run";
45  
46      private static final String TEST_SUITE = "junit.framework.TestSuite";
47  
48      private final Class[] interfacesImplementedByDynamicProxy;
49  
50      private final Class testResultClass;
51  
52      private final Method addListenerMethod;
53  
54      private final Method testInterfaceRunMethod;
55  
56      private static final Class[] EMPTY_CLASS_ARRAY = new Class[0];
57  
58      private static final Object[] EMPTY_OBJECT_ARRAY = new Object[0];
59  
60      private final Class testInterface;
61  
62      private final Class testCase;
63  
64      private final Constructor testsSuiteConstructor;
65  
66      public JUnit3Reflector( ClassLoader testClassLoader )
67      {
68          testResultClass = ReflectionUtils.tryLoadClass( testClassLoader, TEST_RESULT );
69          testCase = ReflectionUtils.tryLoadClass( testClassLoader, TEST_CASE );
70          testInterface = ReflectionUtils.tryLoadClass( testClassLoader, TEST );
71          interfacesImplementedByDynamicProxy =
72              new Class[]{ ReflectionUtils.tryLoadClass( testClassLoader, TEST_LISTENER ) };
73          Class[] constructorParamTypes = { Class.class };
74  
75          Class testSuite = ReflectionUtils.tryLoadClass( testClassLoader, TEST_SUITE );
76  
77          // The interface implemented by the dynamic proxy (TestListener), happens to be
78          // the same as the param types of TestResult.addTestListener
79          Class[] addListenerParamTypes = interfacesImplementedByDynamicProxy;
80  
81          if ( isJUnit3Available() )
82          {
83              testsSuiteConstructor = ReflectionUtils.getConstructor( testSuite, constructorParamTypes );
84              addListenerMethod = tryGetMethod( testResultClass, ADD_LISTENER_METHOD, addListenerParamTypes );
85              testInterfaceRunMethod = getMethod( testInterface, RUN_METHOD, new Class[]{ testResultClass } );
86          }
87          else
88          {
89              testsSuiteConstructor = null;
90              addListenerMethod = null;
91              testInterfaceRunMethod = null;
92          }
93      }
94  
95      // Switch to reflectionutils when building with 2.7.2
96      private static Method tryGetMethod( Class clazz, String methodName, Class[] parameters )
97      {
98          try
99          {
100             return clazz.getMethod( methodName, parameters );
101         }
102         catch ( NoSuchMethodException e )
103         {
104             return null;
105         }
106     }
107 
108     private static Method getMethod( Class clazz, String methodName, Class[] parameters )
109     {
110         try
111         {
112             return clazz.getMethod( methodName, parameters );
113         }
114         catch ( NoSuchMethodException e )
115         {
116             throw new RuntimeException( "When finding method " + methodName, e );
117         }
118     }
119 
120 
121     public Object constructTestObject( Class testClass )
122         throws IllegalAccessException, InvocationTargetException, NoSuchMethodException, InstantiationException
123     {
124         Object testObject = createInstanceFromSuiteMethod( testClass );
125 
126         if ( testObject == null && testCase.isAssignableFrom( testClass ) )
127         {
128             Object[] constructorParams = { testClass };
129 
130             testObject = testsSuiteConstructor.newInstance( constructorParams );
131         }
132 
133         if ( testObject == null )
134         {
135             Constructor testConstructor = getTestConstructor( testClass );
136 
137             if ( testConstructor.getParameterTypes().length == 0 )
138             {
139                 testObject = testConstructor.newInstance( EMPTY_OBJECT_ARRAY );
140             }
141             else
142             {
143                 testObject = testConstructor.newInstance( testClass.getName() );
144             }
145         }
146         return testObject;
147     }
148 
149     private static Object createInstanceFromSuiteMethod( Class testClass )
150         throws IllegalAccessException, InvocationTargetException
151     {
152         Object testObject = null;
153         try
154         {
155             Method suiteMethod = testClass.getMethod( "suite", EMPTY_CLASS_ARRAY );
156 
157             if ( Modifier.isPublic( suiteMethod.getModifiers() ) && Modifier.isStatic( suiteMethod.getModifiers() ) )
158             {
159                 testObject = suiteMethod.invoke( null, EMPTY_CLASS_ARRAY );
160             }
161         }
162         catch ( NoSuchMethodException e )
163         {
164             // No suite method
165         }
166         return testObject;
167     }
168 
169     private static Constructor getTestConstructor( Class testClass )
170         throws NoSuchMethodException
171     {
172         Constructor constructor;
173         try
174         {
175             constructor = testClass.getConstructor( new Class[]{ String.class } );
176         }
177         catch ( NoSuchMethodException e )
178         {
179             constructor = testClass.getConstructor( EMPTY_CLASS_ARRAY );
180         }
181         return constructor;
182     }
183 
184     public Class[] getInterfacesImplementedByDynamicProxy()
185     {
186         return interfacesImplementedByDynamicProxy;
187     }
188 
189     public Class getTestResultClass()
190     {
191         return testResultClass;
192     }
193 
194     public Method getAddListenerMethod()
195     {
196         return addListenerMethod;
197     }
198 
199     public Method getTestInterfaceRunMethod()
200     {
201         return testInterfaceRunMethod;
202     }
203 
204     public Class getTestInterface()
205     {
206         return testInterface;
207     }
208 
209     public Method getRunMethod( Class testClass )
210     {
211         return getMethod( testClass, RUN_METHOD, new Class[]{ getTestResultClass() } );
212     }
213 
214     public boolean isJUnit3Available()
215     {
216         return testResultClass != null;
217     }
218 }